/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mindorks.placeholderview;

import com.mindorks.placeholderview.impl.ICardState;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.Component;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * CardTouchEventListener
 *
 * @since 2021-05-27
 */
public class CardTouchEventListener implements Component.TouchEventListener {
    public static final float cardRotation = 12;
    private Point pointerCurrentPoint = new Point();
    private Point pointerStartingPoint = new Point();
    private Rect startRect;
    private Rect currentRect;
    private final Display displayMetrics;
    private final ICardState iCardState;
    private int mSwipeType = SwipeDirectionalView.SWIPE_TYPE_DEFAULT;

    /**
     * 构造函数
     *
     * @param context   上下文
     * @param cardState 卡片状态
     */
    public CardTouchEventListener(Context context, ICardState cardState) {
        this.iCardState = cardState;
        displayMetrics = DisplayManager.getInstance().getDefaultDisplay(context).get();
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        int dx;
        int dy;

        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                pointerStartingPoint.modify(event.getPointerScreenPosition(0).getX(),
                        event.getPointerScreenPosition(0).getY());

                startRect = component.getComponentPosition();
                break;
            case TouchEvent.OTHER_POINT_UP:
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                pointerCurrentPoint.modify(event.getPointerScreenPosition(0).getX(),
                        event.getPointerScreenPosition(0).getY());
                dx = (int) (pointerCurrentPoint.getPointX() - pointerStartingPoint.getPointX());
                dy = (int) (pointerCurrentPoint.getPointY() - pointerStartingPoint.getPointY());

                int halfWidth = displayMetrics.getAttributes().width / 2;
                int halfHeight = displayMetrics.getAttributes().height / 3;

                if (Math.abs(dx) > halfWidth || Math.abs(dy) > halfHeight) {
                    int removeType = SwipeDirectionalView.BOTTOM_LEFT;
                    if (dx < 0 && dy < 0) {
                        removeType = SwipeDirectionalView.TOP_LEFT;
                    } else if (dx > 0 && dy < 0) {
                        removeType = SwipeDirectionalView.TOP_RIGHT;
                    } else if (dx < 0 && dy > 0) {
                        removeType = SwipeDirectionalView.BOTTOM_LEFT;
                    } else if (dx > 0 && dy > 0) {
                        removeType = SwipeDirectionalView.BOTTOM_RIGHT;
                    }

                    iCardState.removeCardView(component, removeType);
                } else {
                    component.setComponentPosition(startRect);
                    animaReset(component);
                    iCardState.resetCard(component);
                }
                break;
            case TouchEvent.POINT_MOVE:
                pointerCurrentPoint.modify(event.getPointerScreenPosition(0).getX(),
                        event.getPointerScreenPosition(0).getY());

                dy = (int) (pointerCurrentPoint.getPointY() - pointerStartingPoint.getPointY());
                dx = (int) (pointerCurrentPoint.getPointX() - pointerStartingPoint.getPointX());

                if (mSwipeType == SwipeDirectionalView.SWIPE_TYPE_HORIZONTAL) {
                    currentRect = new Rect(startRect.left + dx,
                            startRect.top,
                            startRect.right + dx,
                            startRect.bottom);

                    if (dx < 0) {
                        iCardState.rejectCard(component);
                    } else if (dx > 0) {
                        iCardState.acceptCard(component);
                    }
                } else {
                    currentRect = new Rect(startRect.left + dx,
                            startRect.top + dy,
                            startRect.right + dx,
                            startRect.bottom + dy);

                    if (dx < 0 && dy < 0) {
                        rotateAnima(component, cardRotation);
                        iCardState.rejectCard(component);
                    } else if (dx > 0 && dy < 0) {
                        rotateAnima(component, -cardRotation);
                        iCardState.acceptCard(component);
                    } else if (dx < 0 && dy > 0) {
                        rotateAnima(component, -cardRotation);
                        iCardState.rejectCard(component);
                    } else if (dx > 0 && dy > 0) {
                        rotateAnima(component, cardRotation);
                        iCardState.acceptCard(component);
                    } else if (dx < 0 && dy == 0) {
                        iCardState.rejectCard(component);
                    } else if (dx > 0 && dy == 0) {
                        iCardState.acceptCard(component);
                    } else if (dy > 0 && dx == 0) {
                        iCardState.acceptCard(component);
                    } else if (dy < 0 && dx == 0) {
                        iCardState.rejectCard(component);
                    }
                }

                component.setComponentPosition(currentRect);
                break;
            default:
                break;
        }
        return true;
    }

    public void setSwipeType(int type) {
        this.mSwipeType = type;
    }

    private void rotateAnima(Component component, float rotation) {
        AnimatorProperty animatorProperty = component.createAnimatorProperty();
        animatorProperty
                .rotate(rotation)
                .setCurveType(Animator.CurveType.DECELERATE)
                .setDuration(50)
                .start();
    }

    private void animaReset(Component component) {
        AnimatorProperty animatorProperty = component.createAnimatorProperty();
        animatorProperty
                .rotate(0)
                .setCurveType(Animator.CurveType.DECELERATE)
                .setDuration(50)
                .start();
    }
}
